/* $Id: Application.java 60 2010-02-01 19:54:35Z aaron.day $ */
package org.crazydays.gameplan;


import java.awt.Dimension;

import javax.swing.JFrame;
import javax.swing.SwingUtilities;

import org.apache.commons.configuration.ConfigurationException;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.crazydays.gameplan.db.Database;
import org.crazydays.gameplan.model.IDatabaseObserver;
import org.crazydays.gameplan.swing.ApplicationComponentListener;
import org.crazydays.gameplan.view.View;
import org.crazydays.i18n.Messages;

/**
 * SApplication
 */
public class Application
    extends JFrame
    implements IDatabaseObserver
{
    /** serial version uid */
    public final static long serialVersionUID =
        "$Id: Application.java 60 2010-02-01 19:54:35Z aaron.day $".hashCode();

    /** logger */
    protected final static Logger LOGGER =
        LoggerFactory.getLogger(Application.class);

    /** messages */
    protected final static Messages messages = Messages.getInstance();

    /** resource key: application */
    public final static String RESKEY_APPLICATION = "GamePlan.application";

    /** application location x */
    public final static String APPLICATION_X = "application.location.x";

    /** application location y */
    public final static String APPLICATION_Y = "application.location.y";

    /** application width */
    public final static String APPLICATION_WIDTH = "application.width";

    /** application height */
    public final static String APPLICATION_HEIGHT = "application.height";

    /**
     * Main
     * 
     * @param arguments Arguments
     */
    public final static void main(final String[] arguments)
    {
        final Application application = new Application();

        // fire up application in swing
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                application.initialize();
                application.setVisible(true);
            }
        });

        // shutdown hook to save preferences
        Runtime.getRuntime().addShutdownHook(new Thread()
        {
            public void run()
            {
                // save preferences on shutdown
                try {
                    application.getPreferences().save();
                } catch (ConfigurationException e) {
                    LOGGER.warn("Unable to save preferences", e);
                }
            }
        });
    }

    /** preferences */
    protected Preferences preferences = new Preferences();

    /**
     * Application constructor.
     */
    public Application()
    {
        super(messages.getMessage(RESKEY_APPLICATION));
    }

    /**
     * Initialize application.
     * 
     * @param arguments Arguments
     */
    protected void initialize()
    {
        initializeWindowGeometry();
        initializeIcon();

        ApplicationContext context =
            new ClassPathXmlApplicationContext(
                new String[] { "gameplan.ioc.xml" });

        setRootPane(context.getBean("view", View.class));

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        pack();
    }

    /**
     * Initialize window geometry.
     */
    protected void initializeWindowGeometry()
    {
        initializeLocation();
        initializePreferredSize();
        initializeGeometryListener();
    }

    /**
     * Initialize geometry listener.
     */
    protected void initializeGeometryListener()
    {
        addComponentListener(new ApplicationComponentListener(preferences));
    }

    /**
     * Initialize location.
     */
    protected void initializeLocation()
    {
        int x = preferences.getInt(APPLICATION_X, 48);
        int y = preferences.getInt(APPLICATION_Y, 48);

        setLocation(x, y);
    }

    /**
     * Initialize preferred size.
     */
    protected void initializePreferredSize()
    {
        int width = preferences.getInt(APPLICATION_WIDTH, 800);
        int height = preferences.getInt(APPLICATION_HEIGHT, 600);

        setPreferredSize(new Dimension(width, height));
    }

    /**
     * Initialize icon.
     */
    protected void initializeIcon()
    {
        setIconImage(new Logo(64, 64).getImage());
    }

    /**
     * Get preferences.
     * 
     * @return Preferences
     */
    protected Preferences getPreferences()
    {
        return preferences;
    }

    /**
     * Database opened.
     * 
     * @param database Database
     * @see IDatabaseObserver#opened(Database)
     */
    @Override
    public void opened(Database database)
    {
        setTitle(messages.format("GamePlan.application.1", database.getName()));
    }

    /**
     * Database closed.
     * 
     * @param database Database
     * @see IDatabaseObserver#closed(Database)
     */
    @Override
    public void closed(Database database)
    {
        setTitle(messages.format("GamePlan.application"));
    }
}
